package wypozyczalnia.dao;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import javax.persistence.FetchType;
import javax.persistence.criteria.Fetch;
import javax.persistence.criteria.JoinType;

import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.hibernate.jdbc.Work;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Repository;

import wypozyczalnia.domain.Movie;

@Repository
public class MovieDao extends GenericDao<Movie> {

	@Autowired
	public MovieDao(SessionFactory sf) {
		super(Movie.class, sf);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Movie> getAll() {
		return getHibernateTemplate().find("from Movie");
	}

	@SuppressWarnings("unchecked")
	public List<Object[]> getMovieSearch(final String term, final int LIMIT) {
		return getHibernateTemplate().executeFind(new HibernateCallback() {
			public List<Object[]> doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query createQuery = session
						.createQuery("select     movie.brand,    movie.model,    movie.color,    movie.year, movie.idMovie from Movie as movie where     movie.avalible = 1 and(     upper(movie.model) like :term or     upper(movie.color) like :term or     upper(movie.year) like :term )order by movie.id");

				createQuery.setString("term", "%" + term.toUpperCase() + "%");

				createQuery.setMaxResults(LIMIT);
				return createQuery.list();
			}
		});
	}

	@SuppressWarnings("unchecked")
	/** Pobiera filmy z bazy na podstawie id gatunkus */
	public List<Movie> getMovieByGenre(Integer id) {

		DetachedCriteria dc = DetachedCriteria.forClass(Movie.class);
		dc = dc.createCriteria("genre");
		Criterion genreIdCriterion = Restrictions.eq("idGenre", id);
		dc.add(genreIdCriterion);

		return getHibernateTemplate().findByCriteria(dc);

	}

	public List<Movie> getMovieByTitle(String p_searchedMovie) {
		return getHibernateTemplate().find(
				"from Movie where title='" + p_searchedMovie + "'");
	}

	public Movie getMovieById(Integer id) {
		Movie movie = (Movie) getById(id);
		Hibernate.initialize(movie.getPhotos());
		Hibernate.initialize(movie.getGenre());
		Hibernate.initialize(movie.getPersons());
		Hibernate.initialize(movie.getHires());
		return movie;
	}

	public List<Movie> getMoviesByIds(List<String> idList) {
		String query = "from Movie movie ";
		boolean first = true;
		for (String i : idList) {
			if (first) {
				query += "where movie.idMovie=" + i + " ";
				first = false;
			}

			query += " or movie.idMovie=" + i + " ";
		}
		return getHibernateTemplate().find(query);
	}
	
	public void deleteMovie(final Integer id){
		this.getSession().doWork(new Work() {

			public void execute(Connection conn) {
				CallableStatement stmt = null;
				try {
					stmt = conn.prepareCall("call DELETE_MOVIE(?)");
				} catch (SQLException e1) {

					e1.printStackTrace();
				}
				try {
					stmt.setInt(1, id.intValue());

				} catch (SQLException e) {

					e.printStackTrace();
				}
				try {
					stmt.execute();
				} catch (SQLException e) {

					e.printStackTrace();
				}
			}
		});
	}

	public void setAvailable(final Integer id) {
		this.getSession().doWork(new Work() {

			public void execute(Connection conn) {
				CallableStatement stmt = null;
				try {
					stmt = conn.prepareCall("call SET_AVAIBLE(?,?)");
				} catch (SQLException e1) {

					e1.printStackTrace();
				}
				try {
					stmt.setInt(1, id.intValue());
					stmt.setInt(2, 1);

				} catch (SQLException e) {

					e.printStackTrace();
				}
				try {
					stmt.execute();
				} catch (SQLException e) {

					e.printStackTrace();
				}
			}
		});
	}
}
